package com.hafiery.sdk.bluetooth.transport.engine;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.SparseArray;
import com.hafiery.sdk.bluetooth.transport.callback.CallBackHandler;
import com.hafiery.sdk.bluetooth.transport.constant.ErrorCode;
import com.hafiery.sdk.bluetooth.transport.req.RequestData;
import com.hafiery.sdk.bluetooth.transport.res.ResponseData;
import com.hafiery.sdk.bluetooth.transport.task.Task;
import com.hafiery.sdk.bluetooth.transport.task.TaskManager;
import com.hafiery.sdk.bluetooth.util.LogUtil;


public class EngineWrapper extends Engine{
    private TaskManager taskManager;
    private SparseArray<CallBackHandler> callbackCaches=new SparseArray<>();
    private SparseArray<ResponseData> responseCaches =new SparseArray<>();
//    private TimeoutHandler timeoutHandler=new TimeoutHandler(Looper.getMainLooper());
    public EngineWrapper(BluetoothGatt bluetoothGatt, BluetoothGattCharacteristic charaWrite){
        super(bluetoothGatt, charaWrite);
        taskManager=new TaskManager(new Engine(bluetoothGatt,charaWrite));
    }

    public TaskManager getTaskManager() {
        return taskManager;
    }

    @Override
    public <T> void send(RequestData requestData, CallBackHandler<T> callBack) {
        int opCode=requestData.getOpCode();
        if(callbackCaches.get(opCode)==null){
            callbackCaches.put(opCode,callBack);
        }
//        super.send(requestData,callBack);
//        timeoutHandler.timeout(opCode);
        taskManager.addTask(new Task(requestData,callBack));
    }

    @Override
    public void received(ResponseData responseData) {
        taskManager.next();
        int opCode=responseData.getOpCode();
//        timeoutHandler.cancel(opCode);
        ResponseData responseData1=responseCaches.get(opCode);
        if(responseData1==null){
            responseData1=ResponseData.from(responseData.getOpCode(),responseData.getErrorCode(),responseData.isDone());
            responseCaches.put(opCode,responseData1);
        }
        responseData1.feedValue(responseData.getData());
        if(responseData.isDone()){
            responseCaches.remove(opCode);
            CallBackHandler callBackHandler=callbackCaches.get(responseData1.getOpCode());
            if(callBackHandler!=null){
                callbackCaches.remove(responseData1.getOpCode());
                int errorCode=responseData1.getErrorCode();
                if(errorCode!=0){
                    callBackHandler.callback.onFailure(ErrorCode.of(errorCode));
                }else{
                    Object o=callBackHandler.dataAdapter.parse(responseData1.getData());
                    callBackHandler.callback.onSuccess(o);
                }
            }
        }
    }

    private class TimeoutHandler extends Handler{
        public TimeoutHandler(Looper looper) {
            super(looper);
        }

        public void timeout(int opcode){
            sendEmptyMessageDelayed(opcode,10*1000);
        }
        public void cancel(int opcode){
            removeMessages(opcode);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            int opCode=msg.what;
            CallBackHandler callBackHandler=callbackCaches.get(opCode);
            if(callBackHandler!=null){
                callbackCaches.remove(opCode);
                callBackHandler.callback.onFailure(ErrorCode.ERRCODE_DEVICE_BUSY);
            }
        }
    }
}
